package org.u2ml.stack.db.hibernate;
import java.util.Set;

import javax.persistence.Entity;

import org.hibernate.HibernateException;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.u2ml.Main;


public class XLocalSessionFactoryBean extends LocalSessionFactoryBean {
	private final Logger logger = LoggerFactory.getLogger(XLocalSessionFactoryBean.class);

	public XLocalSessionFactoryBean() {
		super();
	}

	@Override
	protected Configuration newConfiguration() throws HibernateException {
		return new AnnotationConfiguration();
	}
	
	@Override
	protected void postProcessMappings(Configuration config)
			throws HibernateException {
		super.postProcessMappings(config);
		
		AnnotationConfiguration aconfig = (AnnotationConfiguration) config;
		
		scanEntities(aconfig);
	}

	private void scanEntities(AnnotationConfiguration aconfig) {
		ClassPathScanningCandidateComponentProvider entitiesScanner = 
			new ClassPathScanningCandidateComponentProvider(false);
		
		entitiesScanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
		logger.debug("scanning classpath for entity classes...");
		Set<BeanDefinition> candidates = entitiesScanner.findCandidateComponents(Main.class.getPackage().getName());
		logger.info("found {} entity classes", candidates.size());
		
		for (BeanDefinition candidate : candidates) {
			try {
				// register the class to hibernate
				Class<?> clazz = Class.forName(candidate.getBeanClassName());
				
				aconfig.addAnnotatedClass(clazz);
			} catch (ClassNotFoundException e) {
				throw new IllegalStateException(e);
			}
		}
	}
}